package com.codeplatform.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.regex.Pattern;

/**
 * 代码安全验证器
 * 检查用户提交的代码是否包含危险操作
 */
@Slf4j
@Component
public class SecurityValidator {
    
    /**
     * 危险关键词列表
     */
    private static final Map<String, List<String>> DANGEROUS_KEYWORDS = new HashMap<>();
    
    /**
     * 危险正则表达式
     */
    private static final Map<String, List<Pattern>> DANGEROUS_PATTERNS = new HashMap<>();
    
    static {
        initializeDangerousKeywords();
        initializeDangerousPatterns();
    }
    
    /**
     * 初始化危险关键词
     */
    private static void initializeDangerousKeywords() {
        // Python危险关键词
        DANGEROUS_KEYWORDS.put("python", Arrays.asList(
            "__import__", "exec", "eval", "compile", "open", "file",
            "input", "raw_input", "reload", "vars", "dir", "globals", "locals",
            "subprocess", "os.system", "os.popen", "os.spawn", "os.exec",
            "commands", "popen2", "popen3", "popen4",
            "socket", "urllib", "urllib2", "httplib", "ftplib",
            "pickle", "cPickle", "marshal", "shelve",
            "sys.exit", "quit", "exit", "sys.path",
            "importlib", "pkgutil", "imp"
        ));
        
        // Java危险关键词
        DANGEROUS_KEYWORDS.put("java", Arrays.asList(
            "Runtime", "ProcessBuilder", "System.exit", "System.gc",
            "Thread", "ThreadGroup", "ClassLoader", "SecurityManager",
            "File", "FileInputStream", "FileOutputStream", "FileReader", "FileWriter",
            "Socket", "ServerSocket", "URL", "URLConnection",
            "Reflection", "Class.forName", "Method.invoke",
            "System.getProperty", "System.setProperty", "System.getenv",
            "sun.", "com.sun.", "java.lang.reflect"
        ));
        
        // C/C++危险关键词
        DANGEROUS_KEYWORDS.put("c", Arrays.asList(
            "system", "exec", "popen", "fork", "vfork",
            "fopen", "freopen", "remove", "rename",
            "exit", "abort", "_exit",
            "signal", "kill", "raise",
            "malloc", "calloc", "realloc", "free",
            "gets", "scanf", "sprintf", "strcpy", "strcat"
        ));
        
        DANGEROUS_KEYWORDS.put("cpp", DANGEROUS_KEYWORDS.get("c"));
        
        // JavaScript危险关键词
        DANGEROUS_KEYWORDS.put("javascript", Arrays.asList(
            "eval", "Function", "setTimeout", "setInterval",
            "require", "import", "process", "global",
            "Buffer", "fs", "path", "os", "child_process",
            "cluster", "crypto", "http", "https", "net",
            "url", "querystring", "stream", "util",
            "vm", "worker_threads"
        ));
        
        // Go危险关键词
        DANGEROUS_KEYWORDS.put("go", Arrays.asList(
            "os.Exit", "os.Exec", "os.StartProcess",
            "exec.Command", "exec.CommandContext",
            "syscall", "unsafe",
            "os.Open", "os.Create", "os.Remove",
            "net.Dial", "net.Listen", "http.Get", "http.Post",
            "runtime.GC", "runtime.GOMAXPROCS"
        ));
        
        // Rust危险关键词
        DANGEROUS_KEYWORDS.put("rust", Arrays.asList(
            "std::process", "std::fs", "std::net",
            "unsafe", "std::ptr", "std::mem",
            "std::os", "std::env", "std::thread",
            "std::sync", "std::io"
        ));
    }
    
    /**
     * 初始化危险正则表达式
     */
    private static void initializeDangerousPatterns() {
        // 通用危险模式
        List<Pattern> commonPatterns = Arrays.asList(
            Pattern.compile("\\b(rm|del|delete)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(format|fdisk)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(shutdown|reboot|halt)\\s*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(passwd|sudo|su)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(wget|curl|fetch)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(nc|netcat|telnet)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(ping|nmap|nslookup)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(chmod|chown|chgrp)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(mount|umount)\\s+.*", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\b(iptables|firewall)\\s+.*", Pattern.CASE_INSENSITIVE)
        );
        
        // 为每种语言添加通用模式
        for (String language : DANGEROUS_KEYWORDS.keySet()) {
            DANGEROUS_PATTERNS.put(language, new ArrayList<>(commonPatterns));
        }
        
        // Python特定模式
        DANGEROUS_PATTERNS.get("python").addAll(Arrays.asList(
            Pattern.compile("__.*__\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bimport\\s+(os|sys|subprocess|socket|urllib)", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bfrom\\s+(os|sys|subprocess|socket|urllib)", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bopen\\s*\\(.*['\"].*['\"].*['\"][wa]", Pattern.CASE_INSENSITIVE)
        ));
        
        // Java特定模式
        DANGEROUS_PATTERNS.get("java").addAll(Arrays.asList(
            Pattern.compile("\\bRuntime\\.getRuntime\\(\\)", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bClass\\.forName\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bnew\\s+ProcessBuilder\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bnew\\s+File\\s*\\(", Pattern.CASE_INSENSITIVE)
        ));
        
        // C/C++特定模式
        DANGEROUS_PATTERNS.get("c").addAll(Arrays.asList(
            Pattern.compile("\\bsystem\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bpopen\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bfork\\s*\\(", Pattern.CASE_INSENSITIVE),
            Pattern.compile("\\bmalloc\\s*\\(.*\\*.*\\)", Pattern.CASE_INSENSITIVE)
        ));
        
        DANGEROUS_PATTERNS.put("cpp", new ArrayList<>(DANGEROUS_PATTERNS.get("c")));
    }
    
    /**
     * 验证代码安全性（加强版）
     */
    public boolean validateCode(String language, String code) {
        try {
            language = language.toLowerCase();
            
            // 1. 检查代码长度
            if (code.length() > 50000) {
                log.warn("代码长度超限: {} 字符", code.length());
                return false;
            }
            
            // 2. 检查空代码
            if (code.trim().isEmpty()) {
                log.warn("代码内容为空");
                return false;
            }
            
            // 3. 检查危险关键词
            if (!checkDangerousKeywords(language, code)) {
                return false;
            }
            
            // 4. 检查危险模式
            if (!checkDangerousPatterns(language, code)) {
                return false;
            }
            
            // 5. 检查特殊字符和编码
            if (!checkSpecialCharacters(code)) {
                return false;
            }
            
            // 6. 检查代码复杂度
            if (!checkCodeComplexity(code)) {
                return false;
            }
            
            // 7. 检查网络相关操作
            if (!checkNetworkOperations(language, code)) {
                return false;
            }
            
            // 8. 检查文件系统操作
            if (!checkFileSystemOperations(language, code)) {
                return false;
            }
            
            // 9. 检查进程和系统调用
            if (!checkProcessOperations(language, code)) {
                return false;
            }
            
            // 10. 检查内存操作
            if (!checkMemoryOperations(language, code)) {
                return false;
            }
            
            // 11. 检查加密和哈希操作
            if (!checkCryptographicOperations(language, code)) {
                return false;
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("代码安全验证异常", e);
            return false;
        }
    }
    
    /**
     * 检查危险关键词
     */
    private boolean checkDangerousKeywords(String language, String code) {
        List<String> keywords = DANGEROUS_KEYWORDS.get(language);
        if (keywords == null) {
            return true;
        }
        
        String codeToCheck = code.toLowerCase();
        for (String keyword : keywords) {
            if (codeToCheck.contains(keyword.toLowerCase())) {
                log.warn("发现危险关键词: {} in language: {}", keyword, language);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查危险模式
     */
    private boolean checkDangerousPatterns(String language, String code) {
        List<Pattern> patterns = DANGEROUS_PATTERNS.get(language);
        if (patterns == null) {
            return true;
        }
        
        for (Pattern pattern : patterns) {
            if (pattern.matcher(code).find()) {
                log.warn("发现危险模式: {} in language: {}", pattern.pattern(), language);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查特殊字符
     */
    private boolean checkSpecialCharacters(String code) {
        // 检查是否包含过多的特殊字符或控制字符
        int specialCharCount = 0;
        for (char c : code.toCharArray()) {
            if (Character.isISOControl(c) && c != '\n' && c != '\r' && c != '\t') {
                specialCharCount++;
            }
        }
        
        if (specialCharCount > 10) {
            log.warn("代码包含过多控制字符: {}", specialCharCount);
            return false;
        }
        
        return true;
    }
    
    /**
     * 检查代码复杂度
     */
    private boolean checkCodeComplexity(String code) {
        // 检查嵌套层数
        int maxNesting = 0;
        int currentNesting = 0;
        
        for (char c : code.toCharArray()) {
            if (c == '{' || c == '(' || c == '[') {
                currentNesting++;
                maxNesting = Math.max(maxNesting, currentNesting);
            } else if (c == '}' || c == ')' || c == ']') {
                currentNesting--;
            }
        }
        
        if (maxNesting > 20) {
            log.warn("代码嵌套层数过深: {}", maxNesting);
            return false;
        }
        
        // 检查行数
        int lineCount = code.split("\n").length;
        if (lineCount > 1000) {
            log.warn("代码行数过多: {}", lineCount);
            return false;
        }
        
        return true;
    }
    
    /**
     * 获取安全建议
     */
    public List<String> getSecuritySuggestions(String language, String code) {
        List<String> suggestions = new ArrayList<>();
        
        language = language.toLowerCase();
        
        // 检查并给出建议
        if (DANGEROUS_KEYWORDS.containsKey(language)) {
            for (String keyword : DANGEROUS_KEYWORDS.get(language)) {
                if (code.toLowerCase().contains(keyword.toLowerCase())) {
                    suggestions.add("避免使用危险函数: " + keyword);
                }
            }
        }
        
        if (code.length() > 10000) {
            suggestions.add("建议减少代码长度，当前: " + code.length() + " 字符");
        }
        
        int lineCount = code.split("\n").length;
        if (lineCount > 500) {
            suggestions.add("建议减少代码行数，当前: " + lineCount + " 行");
        }
        
        return suggestions;
    }
    
    /**
     * 检查网络相关操作
     */
    private boolean checkNetworkOperations(String language, String code) {
        List<String> networkPatterns = Arrays.asList(
            // HTTP/HTTPS 请求
            "http://", "https://", "urllib", "requests", "fetch", "axios",
            "HttpURLConnection", "URLConnection", "OkHttp", "RestTemplate",
            "curl", "wget", "socket", "ServerSocket", "DatagramSocket",
            // 网络库和模块
            "java.net", "urllib.request", "urllib2", "httplib", "http.client",
            "requests.get", "requests.post", "XMLHttpRequest",
            // 端口和IP
            "bind\\(", "connect\\(", "listen\\(", "accept\\(",
            "gethostbyname", "getaddrinfo", "inet_addr"
        );
        
        for (String pattern : networkPatterns) {
            if (code.toLowerCase().contains(pattern.toLowerCase()) || 
                code.matches("(?i).*" + pattern + ".*")) {
                log.warn("检测到网络操作: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查文件系统操作
     */
    private boolean checkFileSystemOperations(String language, String code) {
        List<String> filePatterns = Arrays.asList(
            // 文件操作
            "open\\(", "file\\(", "fopen", "fwrite", "fread", "fclose",
            "FileInputStream", "FileOutputStream", "FileReader", "FileWriter",
            "Files.write", "Files.read", "Files.delete", "Files.copy",
            // 目录操作
            "mkdir", "rmdir", "listdir", "os.walk", "glob.glob",
            "File.createNewFile", "File.delete", "File.mkdir",
            // 路径操作
            "os.path", "pathlib", "Paths.get", "File.separator",
            // 危险路径
            "/etc/", "/proc/", "/sys/", "/dev/", "C:\\\\Windows",
            "../", "..\\\\", "~/"
        );
        
        for (String pattern : filePatterns) {
            if (code.toLowerCase().contains(pattern.toLowerCase()) || 
                code.matches("(?i).*" + pattern + ".*")) {
                log.warn("检测到文件系统操作: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查进程和系统调用
     */
    private boolean checkProcessOperations(String language, String code) {
        List<String> processPatterns = Arrays.asList(
            // 进程执行
            "exec", "system", "popen", "subprocess", "ProcessBuilder",
            "Runtime.getRuntime", "Process.start", "os.system",
            "os.popen", "os.spawn", "commands.getoutput",
            // 系统调用
            "syscall", "ctypes", "libc", "kernel32", "ntdll",
            "GetProcAddress", "LoadLibrary", "dlopen", "dlsym",
            // Shell 命令
            "cmd.exe", "/bin/sh", "/bin/bash", "powershell",
            "sh -c", "bash -c", "cmd /c"
        );
        
        for (String pattern : processPatterns) {
            if (code.toLowerCase().contains(pattern.toLowerCase()) || 
                code.matches("(?i).*" + pattern + ".*")) {
                log.warn("检测到进程/系统调用: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查内存操作
     */
    private boolean checkMemoryOperations(String language, String code) {
        List<String> memoryPatterns = Arrays.asList(
            // 内存分配
            "malloc", "calloc", "realloc", "free", "new\\[", "delete\\[",
            "VirtualAlloc", "HeapAlloc", "mmap", "munmap",
            // 指针操作
            "\\*\\w+\\s*=", "\\w+\\s*->", "\\&\\w+", "sizeof\\(",
            // 内存拷贝
            "memcpy", "memmove", "memset", "strcpy", "strncpy",
            // 缓冲区操作
            "gets\\(", "sprintf\\(", "vsprintf\\(", "strcpy\\("
        );
        
        for (String pattern : memoryPatterns) {
            if (code.matches("(?i).*" + pattern + ".*")) {
                log.warn("检测到内存操作: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
    
    /**
     * 检查加密和哈希操作
     */
    private boolean checkCryptographicOperations(String language, String code) {
        List<String> cryptoPatterns = Arrays.asList(
            // 加密库
            "javax.crypto", "java.security", "Cipher", "MessageDigest",
            "cryptography", "hashlib", "hmac", "ssl", "tls",
            "AES", "DES", "RSA", "SHA", "MD5", "HMAC",
            // 密钥操作
            "KeyGenerator", "SecretKey", "PrivateKey", "PublicKey",
            "KeyPair", "KeyStore", "Certificate"
        );
        
        for (String pattern : cryptoPatterns) {
            if (code.toLowerCase().contains(pattern.toLowerCase()) || 
                code.matches("(?i).*" + pattern + ".*")) {
                log.warn("检测到加密/哈希操作: {}", pattern);
                return false;
            }
        }
        
        return true;
    }
}